home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacHaskell 2.2 / doc / comparison < prev    next >
Encoding:
Text File  |  1994-09-27  |  11.0 KB  |  292 lines  |  [TEXT/ttxt]

  1.  
  2.          Different Versions of Yale Haskell Compared
  3.          -------------------------------------------
  4.  
  5.  
  6. There are currently three different platforms running Yale Haskell.
  7. Yale Haskell runs on Lucid Common Lisp, CMU Common Lisp, and AKCL.  This
  8. document describes the differences between these systems.
  9.  
  10. Differences in performance between the different versions of Yale
  11. Haskell reflect the underlying Lisp systems.  The better the Lisp
  12. system, the better the Haskell system built on it.  However, getting
  13. optimal performance from our Haskell system on top of a Common Lisp
  14. system requires careful attention to the underlying compiler.  Small
  15. changes in the optimization settings or the addition of crucial
  16. declarations can make significant differences in performance.  We have
  17. been doing most of our work using the Lucid system and have tuned it
  18. more than the others.  These comparisons are greatly influenced by the
  19. amount of time we have spent tuning the system: the CMU version has
  20. been tuned only a little and the AKCL version hardly at all.
  21.  
  22.  
  23.   Methodology
  24.  
  25. The following timings are only approximate.  They were obtained using
  26. the timing functions provided by the Common Lisp system.  All timings
  27. were done on an unloaded Sparc 1.  No attempt was made to account for
  28. garbage collection, differences in heap size, or similar factors.  We
  29. don't intend these benchmark results to be taken as an exhaustive
  30. comparison of the different Lisp implementations involved.
  31.  
  32.  
  33.   Portability
  34.  
  35. We have had no trouble moving our system to different hardware
  36. platforms under the same Lisp system.  Since the release is in source
  37. form, we expect that users will be able to build on any hardware
  38. platform supported by one the Lisps we have ported to.  Probably the
  39. only real constraint on portability is the requirement for a large
  40. virtual memory space.  
  41.  
  42. From the comp.lang.lisp FAQ:
  43.  
  44.   Lucid Common Lisp runs on a variety of platforms, including PCs (AIX),
  45.   Apollo, HP, Sun-3, Sparc, IBM RT, IBM RS/6000, Decstation 3100,
  46.   Silicon Graphics, and Vax.
  47.  
  48.   CMU Common Lisp is free, and runs on Sparcs (Mach and SunOs),
  49.   DecStation 3100 (Mach), IBM RT (Mach) and requires 16mb RAM, 25mb disk.
  50.  
  51.   Kyoto Common Lisp (KCL) is free, but requires a license. Conforms to CLtL1.
  52.   It is available by anonymous ftp from rascal.ics.utexas.edu [128.83.138.20],
  53.   cli.com [192.31.85.1], or [133.11.11.11] (a machine in Japan)
  54.   in the directory /pub.  AKCL is in the file akcl-xxx.tar.Z (take the
  55.   highest value of xxx).  To obtain KCL, one  must first sign and mail a
  56.   copy of the license agreement to: Special Interest Group in LISP,
  57.   c/o Taiichi Yuasa, Department of Computer Science,  Toyohashi
  58.   University of Technology, Toyohashi 441, JAPAN. Runs on Sparc,
  59.   IBM RT, RS/6000, DecStation 3100, hp300, hp800, Macintosh II (under AUX),
  60.   mp386, IBM PS2, Silicon Graphics 4d, Sun3, Sun4, Sequent Symmetry,
  61.   IBM 370, NeXT and Vax. A port to DOS is in beta test as
  62.   math.utexas.edu:pub/beta2.zip.
  63.  
  64. We have not yet completed ports of Yale Haskell to any other Lisp
  65. implementations, although we are likely to do so in the future.
  66.  
  67.  
  68.  System Size
  69.  
  70. The overall size of the Haskell system depends on the size of the
  71. underlying Lisp system and how much unnecessary Lisp overhead has been
  72. removed for the system.  We have removed large Lisp packages (like
  73. CLOS or CLX), but have not attempted to do any tree shaking.  The size
  74. of the saved images (including the Lisp system, the Haskell compiler,
  75. and the compiled prelude) is
  76.  
  77. Image Size:
  78.  
  79. Lucid   10 meg
  80. CMU     18 meg
  81. AKCL    11 meg
  82.  
  83. The larger size of the CMU system is probably an artifact of their way
  84. of saving the system.
  85.  
  86.  
  87.   Compilation Time
  88.  
  89. There are three possible ways to compile a Haskell program.  All
  90. Haskell programs must be translated into Lisp.  The generated Lisp can
  91. then be interpreted, using no additional compilation time; compiled
  92. with a `fast' but nonoptimizing Lisp compiler; or compiled with the
  93. `slow' compiler that aggressively attempts to perform as many
  94. optimizations as possible.  
  95.  
  96. To time the `fast', nonoptimizing compiler, we have been using
  97.  
  98. (PROCLAIM '(OPTIMIZE (SPEED 3) (SAFETY 0) (COMPILATION-SPEED 3)))
  99.  
  100. and for the `slow', fully optimizing compiler, we have been using
  101.  
  102. (PROCLAIM '(OPTIMIZE (SPEED 3) (SAFETY 0) (COMPILATION-SPEED 0)))
  103.  
  104. so that the only difference is in the COMPILATION-SPEED quality.
  105. Lucid does, in fact, provide two completely different compilers that
  106. correspond to these optimize settings.  For all three implementations,
  107. it appears that that the effect of a higher compilation speed setting
  108. is primarily in being less aggressive about inlining and making use of
  109. type declarations.
  110.  
  111. The Haskell system itself (including the Prelude) is normally built
  112. with the fully optimizing compiler.
  113.  
  114. To show just the Haskell to Lisp compilation time, here are the times
  115. needed to compile the Prelude (about 2500 lines of Haskell code).
  116. This does not include the time in the Lisp compiler or starting up the
  117. system.
  118.  
  119. Time to compile the Prelude into Lisp: (CPU times)
  120.  
  121. Lucid     111 sec
  122. CMU       87  sec
  123. AKCL      576 sec
  124.  
  125. Running the Lisp compiler on the generated code takes far longer than
  126. running the Haskell compiler to produce the Lisp code.  For example,
  127. the optimizing Lucid compiler takes 47 minutes to compile the Prelude
  128. (about x20 slower than Haskell -> Lisp).  The nonoptimizing compiler
  129. is significantly faster but generates poorer code.
  130.  
  131. The following times are the Lisp compilation time for the Prolog
  132. interpreter (found in the demo directory of our release):
  133.  
  134. Lucid - interpreted     8.8 sec  Haskell -> Lisp
  135. Lucid - nonopt         20.0 sec  Lisp -> Machine code
  136. Lucid - optimizing    320.0 sec  Lisp -> Machine code
  137. CMU - interpreted      12.4 sec  Haskell -> Lisp
  138. CMU - nonopt          121.0 sec  Lisp -> Machine code
  139. CMU - optimizing      152.8 sec  Lisp -> Machine code
  140. AKCL - interpreted     47.8 sec  Haskell -> Lisp
  141. AKCL - nonopt          ~180 sec  Lisp -> Machine code
  142. AKCL - optimizing      ~360 sec  Lisp -> Machine code
  143.  
  144. The AKCL timings are only approximate, because the Lisp timing
  145. functions do not capture the time spent in the C compiler.
  146.  
  147.  
  148. Code Speed
  149.  
  150. The speed of the Haskell program depends on whether the Lisp code
  151. has been compiled with the optimizing or nonoptimizing compiler, or
  152. is running interpretively.
  153.  
  154. The first benchmark is nfib, which indicates the basic speed of
  155. function calling and Int arithmetic.
  156.  
  157. module Main where
  158.  
  159. nfib :: Int -> Int
  160. nfib 0 = 1
  161. nfib 1 = 1
  162. nfib n = nfib (n-1) + nfib (n-2)
  163.  
  164.  
  165.                              nfib 20            nfib 30    
  166. Lucid (Interpreted)          116 sec            *
  167. Lucid (nonopt)               0.14 sec           9.4 sec
  168. Lucid (optimizing)           0.08 sec           4.8 sec
  169. CMU (Interpreted)            23.8 sec           *
  170. CMU (nonopt)                 0.24 sec           6.9 sec
  171. CMU (optimizing)             0.11 sec           7.0 sec
  172. AKCL (Interpreted)           141 sec            *
  173. AKCL (nonopt)                0.20 sec           21.3 sec
  174. AKCL (optimizing)            0.15 sec           18.2 sec
  175.  
  176. * Too slow to benchmark
  177.  
  178. For other data types, there was no significant difference betwen
  179. optimizing and nonoptimizing compilation in any of the systems.
  180. Changing the signature of nfib to Integer -> Integer:
  181.  
  182.                              nfib 20            nfib 30    
  183. Lucid (interpreted)          140 sec            *
  184. Lucid (compiled)             0.18 sec           10.2 sec
  185. CMU (interpreted)            24.2 sec           *
  186. CMU (compiled)               0.16 sec           10.5 sec
  187. AKCL (interpreted)           145 sec            *
  188. AKCL (compiled)              1.07 sec           127 sec
  189.  
  190. Nfib with signature Float -> Float:
  191.  
  192.                              nfib 20            nfib 30    
  193. Lucid (interpreted)          222  sec            *
  194. Lucid (compiled)             16.4 sec           2416 sec
  195. CMU (interpreted)            44.2 sec           *
  196. CMU (compiled)               1.61 sec           352 sec
  197. AKCL (interpreted)           161 sec            *
  198. AKCL (compiled)              103 sec            *
  199.  
  200. Overloaded functions run considerably slower than nonoverloaded
  201. functions.  By allowing nfib to remain overloaded, Num a => a -> a,
  202. and using the Int overloading the same benchmarks run much slower.
  203. Again, there is no real difference between the different compiler
  204. optimization settings.
  205.  
  206.                              nfib 15            nfib 20    
  207. Lucid (interpreted)          14.2 sec           156 sec
  208. Lucid (compiled)             0.97 sec           9.3 sec
  209. CMU (interpreted)            23.8 sec           155 sec
  210. CMU (compiled)               0.89 sec           15.6 sec
  211. AKCL (interpreted)           30.8 sec           387 sec
  212. AKCL (compiled)              10.3 sec           119 sec
  213.  
  214. Basic Haskell data structuring operations (pattern matching and
  215. construction) can be tested using another version of nfib which uses
  216. natural numbers:
  217.  
  218.   data Nat = Z | S Nat
  219.  
  220. The difference betwen CMU and Lucid here is consistent with other
  221. benchmarks that manipulate structures.
  222.  
  223.                              nfib 10            nfib 15
  224. Lucid (Interpreted)          1.39 sec           26.7 sec
  225. Lucid (compiled)             0.26 sec           2.28 sec
  226. CMU (interpreted)            3.1 sec            <stack overflow>
  227. CMU (compiled)               0.16 sec           0.54 sec
  228. AKCL (Interpreted)           4.25 sec           <stack overflow>
  229. AKCL (compiled)              0.21 sec           13.9 sec
  230.  
  231.  
  232.  A Large Program
  233.  
  234. For a final benchmark, we use the Prolog interpreter as a way of
  235. getting a feel for general performance of larger programs.  This
  236. program is typical of symbolic (as opposed to numeric) computation.
  237.  
  238. Time to solve append(X,Y,cons(a,cons(b,cons(c,nil)))):
  239.  
  240. Lucid    12.2 sec
  241. CMU      12.0 sec
  242. AKCL     69.1 sec
  243.  
  244. My interpretation of this result is that although Lucid is a bit
  245. slower on the previous small benchmarks, it makes up for this is
  246. larger programs where advantages like better instruction scheduling,
  247. register allocation, or memory usage may make a difference.  In
  248. general, Lucid and CMU are very similar in performance for larger
  249. programs.
  250.  
  251.  
  252.  Conclusions
  253.  
  254. Briefly stated, the pluses and minuses of each system are as follows:
  255.  
  256. Lucid (4.0.0):
  257.  + Development (nonoptimizing) compiler is very fast
  258.  + Fast Haskell -> Lisp compilation
  259.  + Generates good code
  260.  + Very robust
  261.  - Costs money
  262.  - Slow floating point code
  263.  - Fairly slow interpreter
  264.  - The production (optimizing) compiler is extremely slow.
  265.  
  266. CMU (16e):
  267.  + Free
  268.  + As fast as Lucid for Haskell -> Lisp
  269.  + Good floating point performance
  270.  + Generated code is very fast
  271.  + Fast interpreter
  272.  - Slow Lisp -> machine code compilation
  273.  - Doesn't run on many systems
  274.  
  275. AKCL (1.615):
  276.  + Free
  277.  + Widely portable
  278.  - Slow (generally 3 - 5 times slower, sometimes much worse)
  279.  - Flakey (tends to core dump on errors, choke on large programs, etc.)
  280.  
  281. Generally, using the fully optimizing compiler seems to be useful only
  282. in code involving Int arithmetic.
  283.  
  284. The fast compiler for Lucid is a big advantage, delivering by far the
  285. fastest compilation to machine code with relatively little loss in
  286. speed compared to the optimizing compiler.
  287.  
  288.  
  289.             Yale Haskell Group
  290.             September 25, 1992
  291.  
  292.